package com.king.designpatterns.行为模式.解释器模式;

/**
 * 解释器模式（Interpreter Pattern）是一种按照规定语法对表达式进行解析的方案，在项目中使用较少。
 *
 * 定义：给定一门语言，定义它的文法的一种表示，并定义一个解释器，该解释器使用该表示来解释语言中的句子
 *
 * 角色：
 *      ■ 抽象表达式（Abstract Expression）角色：
 *          该角色声明一个所有的具体表达式角色都需要实现的抽象接口，该接口主要是一个解释操作interpret()方法。
 *      ■ 终结符表达式（Terminal Expression）角色：
 *          该角色实现了抽象表达式角色所要求的接口，文法中的每一个终结符都有一个具体终结表达式与之对应。
 *      ■ 非终结符表达式（Nonterminal Expression）角色：
 *          该角色是一个具体角色，文法中的每一条规则都对应一个非终结符表达式类。
 *      ■ 环境（Context）角色：
 *          该角色提供解释器之外的一些全局信息。
 *      ■ 客户端（Client）角色：
 *          该角色创建一个抽象语法树，调用解释操作。
 *
 * 优缺点：
 *      优点：
 *          ■ 简单的语法分析工具。
 *          ■ 扩展性，修改语法规则只要修改相应的非终结符表达式即可，若扩展语法，则只要增加非终结符类即可。
 *      缺点：
 *          ■ 解释器模式会引起类膨胀。每个语法都要产生一个非终结符表达式，语法比较复杂时就可能产生大量的类文件，不易维护。
 *          ■ 采用递归调用方法。每个非终结符表达式只关心与自己有关的表达式，每个表达式需要知道最终的结果，必须一层一层地剥茧，
 *              无论是面向过程的语言还是面向对象的语言，递归都是在必要条件下使用的，不易调试且影响效率。
 *
 * 场景：
 *      ■ 重复发生的问题可以使用解释器模式。
 *          例如，多个应用服务器，每天产生大量的日志，需要对日志文件进行分析处理，由于各个服务器的日志格式不同，但是数据要素是相同的，
 *          按照解释器的说法就是终结符表达式都是相同的，非终结符表达式就需要制定。
 *      ■ 一个简单语法需要解释的场景。
 *
 * @author king
 * @date 2021-06-11 14:21
 */
public class InterpreterPattern {
    public static void main(String[] args) {
        Variables v = new Variables();
        Variable x = new Variable();
        Variable y = new Variable();
        Variable z = new Variable();
        v.put(x, 10);
        v.put(y, 20);
        v.put(z, 30);

        // 计算 x * (y + z / x) - x => 220
        ArithmeticExpression e = new Substract(new Multiply(x, new Plus(y, new Division(z, x))), x);
        System.out.println(e.interpret(v));
    }
}
